package com.yuehuanghun.framework.web;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.beanutils.PropertyUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.yuehuanghun.framework.domain.PageDTO;
import com.yuehuanghun.framework.exception.BizException;
import com.yuehuanghun.framework.exception.ValidateException;
import com.yuehuanghun.framework.util.StringUtils;
import com.yuehuanghun.framework.util.WrapperHelper;
import com.yuehuanghun.framework.util.http.RequestUtils;
import com.yuehuanghun.framework.util.sql.SqlUtil;
import com.yuehuanghun.mybatis.milu.data.Sort;
import com.yuehuanghun.mybatis.milu.data.Sort.Direction;
import com.yuehuanghun.mybatis.milu.pagehelper.PageRequest;
import com.yuehuanghun.mybatis.milu.pagehelper.Pageable;

import lombok.Getter;
import lombok.Setter;

public class BaseResource {
	private static Logger logger = LoggerFactory.getLogger(BaseResource.class);
	@Autowired
	private HttpServletRequest request;

	private TableSupport tableSupport = new TableSupport();

	/**
	 * 设置返回码
	 * 
	 * @param code
	 * @return
	 */
	public BaseResource setReturnCode(int code) {
		WrapperHelper.setCode(code);
		return this;
	}

	/**
	 * 设置返回消息
	 * 
	 * @param message
	 * @return
	 */
	public BaseResource setReturnMessage(String message) {
		WrapperHelper.setMessage(message);
		return this;
	}

	/**
	 * 设置返回码及返回消息
	 * 
	 * @param code
	 * @param message
	 */
	public void setReturn(int code, String message) {
		WrapperHelper.set(code, message);
	}

	/**
	 * 转换为标准的分页格式
	 * 
	 * @param currPage  当前页，从1开始
	 * @param pageSize  每页行数
	 * @param totalRows 总行数
	 * @param content   内容列表
	 * @return
	 */
	public <T> PageDTO<T> toPage(int currPage, int pageSize, long totalRows, List<T> content) {
		return new PageDTO<>(currPage, pageSize, totalRows, content);
	}

	/**
	 * 转换为标准的分页格式
	 * 
	 * @param <T>
	 * @param page PageHelper分页
	 * @return
	 */
	public <T> PageDTO<T> toPage(Page<T> page) {
		return new PageDTO<>(page.getPageNum(), page.getPageSize(), page.getTotal(), page.getResult());
	}

	public <T> PageDTO<T> toPage(List<T> list) {
		if (list instanceof Page) {
			return toPage((Page<T>) list);
		}
		return new PageDTO<>(0, 0, list.size(), list);
	}

	/**
	 * 非空字符串断言
	 * 
	 * @author yuehuanghun
	 * @param target       判断目标
	 * @param errorMessage 当为空字符串时抛出的异常信息
	 * @date 2017年11月29日 下午3:10:03
	 */
	public void assertNotBlank(String target, String errorMessage) {
		if (StringUtils.isBlank(target)) {
			throw new ValidateException(errorMessage);
		}
	}

	/**
	 * 非null对象断言
	 * 
	 * @author yuehuanghun
	 * @param target       判断目标
	 * @param errorMessage 当为null时抛出的异常信息
	 */
	public void assertNotNull(Object target, String errorMessage) {
		if (target == null) {
			throw new ValidateException(errorMessage);
		}
	}

	/**
	 * 正则匹配断言
	 * 
	 * @author yuehuanghun
	 * @param target
	 * @param regex
	 * @param errorMessage
	 */
	public void assertMatch(String target, String regex, String errorMessage) {
		assertNotNull(target, errorMessage);
		if (!Pattern.matches(regex, target)) {
			throw new ValidateException(errorMessage);
		}
	}

	/**
	 * 真值断言
	 * 
	 * @author yuehuanghun
	 * @param flag
	 * @param errorMessage
	 */
	public void assertTrue(boolean flag, String errorMessage) {
		if (!flag) {
			throw new ValidateException(errorMessage);
		}
	}

	/**
	 * 将列表中的元素转为一个新的列表，提取的元素自设定
	 * 
	 * @author yuehuanghun
	 * @param list
	 * @param properties
	 * @return
	 */
	public List<Map<String, Object>> describeList(List<? extends Object> list, String... properties) {
		if (list == null) {
			list = Collections.emptyList();
		}
		List<Map<String, Object>> resultList = new ArrayList<>();
		Map<String, Object> item;
		for (Object obj : list) {
			item = new HashMap<>();
			resultList.add(item);

			for (String property : properties) {
				try {
					item.put(property, PropertyUtils.getProperty(obj, property));
				} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
					logger.info("", e);
				}
			}
		}
		return resultList;
	}

	/**
	 * 获取当前请求域
	 * 
	 * @param request
	 * @return
	 */
	public String getDomain() {
		if (request == null) {
			throw new BizException("非WEB环境");
		}
		StringBuffer url = request.getRequestURL();
		String contextPath = request.getServletContext().getContextPath();
		return url.delete(url.length() - request.getRequestURI().length(), url.length()).append(contextPath).toString();
	}

	/**
	 * 创建一个HashMap对象
	 * 
	 * @param <K>
	 * @param <V>
	 * @return
	 */
	public <K, V> HashMap<K, V> hashMap() {
		return new HashMap<>();
	}

	/**
	 * 设置请求分页数据
	 */
	protected void startPage() {
		PageDomain pageDomain = tableSupport.buildPageRequest();
		Integer pageNum = pageDomain.getPageNum();
		Integer pageSize = pageDomain.getPageSize();
		if (StringUtils.isNotNull(pageNum) && StringUtils.isNotNull(pageSize)) {
			String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy());
			PageHelper.startPage(pageNum, pageSize, orderBy);
		}
	}	
	
	protected Pageable getPage() {
		PageDomain pageDomain = tableSupport.buildPageRequest();
		Integer pageNum = pageDomain.getPageNum();
		Integer pageSize = pageDomain.getPageSize();
		if (StringUtils.isNotNull(pageNum) && StringUtils.isNotNull(pageSize)) {
			return new PageRequest(pageNum, pageSize, true);
		}
		return null;
	}
	
	/** 获取排序，orderByColumn需要为实体属性名，跟startPage不一样，startPage的orderByColumn需要表列名 */
	protected Sort getSort() {
		PageDomain pageDomain = tableSupport.buildPageRequest();
		if(StringUtils.isBlank(pageDomain.getOrderByColumn())) {
			return Sort.by(PageDomain.ASC.equals(pageDomain.getIsAsc()) ? Direction.ASC : Direction.DESC, pageDomain.getOrderByColumn());
		}
		return null;
	}

	public class TableSupport {
		/**
		 * 当前记录起始索引
		 */
		private final String PAGE_NUM = "pageNum";

		/**
		 * 每页显示记录数
		 */
		private final String PAGE_SIZE = "pageSize";

		/**
		 * 排序列
		 */
		private final String ORDER_BY_COLUMN = "orderByColumn";

		/**
		 * 排序的方向 "desc" 或者 "asc".
		 */
		private final String IS_ASC = "isAsc";

		/**
		 * 默认分页行数
		 */
		private final Integer DEFAULT_PAGE_SIZE = new Integer(10);

		/**
		 * 封装分页对象
		 */
		public PageDomain getPageDomain() {
			PageDomain pageDomain = new PageDomain();
			pageDomain.setPageNum(RequestUtils.getInt(request, PAGE_NUM, 1));
			pageDomain.setPageSize(RequestUtils.getInt(request, PAGE_SIZE, DEFAULT_PAGE_SIZE));
			pageDomain.setOrderByColumn(RequestUtils.getString(request, ORDER_BY_COLUMN, StringUtils.EMPTY));
			pageDomain.setIsAsc(RequestUtils.getString(request, IS_ASC, StringUtils.EMPTY));
			return pageDomain;
		}

		public PageDomain buildPageRequest() {
			return getPageDomain();
		}
	}

	@Getter
	@Setter
	private static class PageDomain {
		private static String ASC = "asc";
		/** 当前记录起始索引 */
		private Integer pageNum;

		/** 每页显示记录数 */
		private Integer pageSize;

		/** 排序列 */
		private String orderByColumn;

		/** 排序的方向desc或者asc */
		private String isAsc = ASC;

		public String getOrderBy() {
			if (StringUtils.isEmpty(orderByColumn)) {
				return "";
			}
			return StringUtils.toUnderScoreCase(orderByColumn) + " " + isAsc;
		}
	}
}
